package cn.piesat.service.impl;

import cn.piesat.dao.*;
import cn.piesat.dto.*;
import cn.piesat.util.JedisUtils;
import cn.piesat.util.PageUtil;
import cn.piesat.util.TreeUtil;
import cn.piesat.util.config.FieldStaticConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.piesat.service.intf.UserInfoService;
import cn.piesat.util.DESEncryptUtil;
import cn.piesat.vo.userInfoConfig.ConfigInfoProjection;
import cn.piesat.vo.userInfoConfig.UpdatePasswordParam;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 用户服务层逻辑实现
 *
 * @author xhl
 */
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private PiesatUserInfoDAO piesatUserInfoDAO;

    @Autowired
    private PiesatUserInfoConfigDAO piesatUserInfoConfigDAO;

    @Autowired
    private PiesatUserConfigInfoDAO piesatUserConfigInfoDAO;

    @Autowired
    private PiesatUserRoleRelationDAO piesatUserRoleRelationDAO;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private PiesatDeptInfoDAO piesatDeptInfoDAO;

    @Autowired
    private PiesatRoleInfoDAO piesatRoleInfoDAO;

    @Autowired
    private PiesatMenuInfoDAO piesatMenuInfoDAO;

    @Autowired
    private PiesatResourceInfoDAO piesatResourceInfoDAO;

    @Autowired
    private PiesatUserLogDAO piesatUserLogDAO;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> addUser(JSONObject params) {
        Map<String,String> resultMap = new HashMap<>();
        List<PiesatUserInfoConfigDTO> formList = piesatUserInfoConfigDAO.findAllByIsNotRegisterOrderByCreateTime(0);
        if (StringUtils.isBlank(params.getString("deptId"))) {
            resultMap.put("success","false");
            resultMap.put("message","部门ID不能为空");
            return resultMap;
        }
        List<PiesatUserConfigInfoDTO> configInfoList = new ArrayList<>();
        //校验参数是否满足必填和规则
        for (PiesatUserInfoConfigDTO configDTO : formList) {
            String field = configDTO.getField();
            if (configDTO.getIsNotFill() == 0 && StringUtils.isBlank(params.getString(field))) {
                resultMap.put("success","false");
                resultMap.put("message",configDTO.getField() + "参数不能为空");
                return resultMap;
            }
            if (StringUtils.isNotBlank(configDTO.getVerifyRule())) {
                Pattern pattern = Pattern.compile(configDTO.getVerifyRule());
                Matcher matcher = pattern.matcher(params.getString(configDTO.getField()));
                if(!matcher.matches()) {
                    resultMap.put("success","false");
                    resultMap.put("message",configDTO.getField() + "不符合校验规则");
                    return resultMap;
                }
            }
            if ("username".equals(field) || "password".equals(field) || "telephone".equals(field) || "email".equals(field)) {
                continue;
            } else {
                PiesatUserConfigInfoDTO configInfoDTO = new PiesatUserConfigInfoDTO();
                configInfoDTO.setUserConfigId(configDTO.getId());
                if ("checkbox".equals(configDTO.getFormType())) {
                    configInfoDTO.setUserConfigInfo(params.getJSONArray(configDTO.getField()).toJSONString());
                } else {
                    configInfoDTO.setUserConfigInfo(params.getString(configDTO.getField()));
                }
                configInfoList.add(configInfoDTO);
            }
        }
        //校验登录方式的凭证是否唯一（用户名、手机号码、邮箱）
        List<PiesatUserInfoConfigDTO> loginConfigList = formList.stream()
                .filter(dto -> dto.getIsNotLogin() == 0)
                .collect(Collectors.toList());
        for (PiesatUserInfoConfigDTO dto : loginConfigList) {
            String field = dto.getField();
            PiesatUserInfoDTO existDTO = null;
            if ("username".equals(field)) {
                existDTO = piesatUserInfoDAO.findByUsername(params.getString(field));
            } else if ("telephone".equals(field)) {
                existDTO = piesatUserInfoDAO.findByMobile(params.getString(field));
            } else if ("email".equals(field)) {
                existDTO = piesatUserInfoDAO.findByEmail(params.getString(field));
            }
            if (existDTO != null) {
                resultMap.put("success","false");
                resultMap.put("message",dto.getFieldName() + "已存在");
                return resultMap;
            }
        }
        //保存基本用户信息
        PiesatUserInfoDTO userInfoDTO = new PiesatUserInfoDTO();
        userInfoDTO.setUsername(params.getString("username"));
        userInfoDTO.setPassword(passwordEncoder.encode(params.getString("password")));
        userInfoDTO.setEmail(params.getString("email"));
        userInfoDTO.setMobile(params.getString("telephone"));
        userInfoDTO.setDeptId(params.getString("deptId"));
        userInfoDTO.setLockState(params.getInteger("lockState"));
        userInfoDTO.setCreateTime(new Date());
        PiesatUserInfoDTO saveUserInfoDTO = piesatUserInfoDAO.save(userInfoDTO);
        //保存额外用户信息
        configInfoList.forEach(dto -> dto.setUserInfoId(saveUserInfoDTO.getId()));
        piesatUserConfigInfoDAO.saveAll(configInfoList);
        //保存用户和角色关系
        JSONArray roleIdList = params.getJSONArray("roleIdList");
        if (!roleIdList.isEmpty()) {
            List<PiesatUserRoleRelationDTO> userRoleList = new ArrayList<>();
            for (Object o : roleIdList) {
                PiesatUserRoleRelationDTO userRole = new PiesatUserRoleRelationDTO();
                userRole.setRoleId(o.toString());
                userRole.setUserId(saveUserInfoDTO.getId());
                userRoleList.add(userRole);
            }
            piesatUserRoleRelationDAO.saveAll(userRoleList);
        }
        resultMap.put("success","true");
        resultMap.put("message","添加成功");
        return resultMap;
    }

    @Override
    public Map<String, Object> search(JSONObject params, Pageable pageable) {
        //竖表转横表SQL
        StringBuilder selectSql = new StringBuilder();
        StringBuilder leftSql = new StringBuilder("(SELECT a.USER_INFO_ID as userId");
        List<PiesatUserInfoConfigDTO> registerConfigList = piesatUserInfoConfigDAO.findAllByIsNotRegisterOrderByCreateTime(0);
        for (PiesatUserInfoConfigDTO configDTO : registerConfigList) {
            String field = configDTO.getField();
            if (!"username".equals(field) && !"password".equals(field) && !"telephone".equals(field) && !"email".equals(field)) {
                leftSql.append(",MAX(CASE FIELD WHEN '")
                        .append(field)
                        .append("' THEN a.USER_CONFIG_INFO END) AS ")
                        .append(field);
                selectSql.append(",b.").append(field).append(" AS ").append(field);
            } else {
                if (!"password".equals(field)) {
                    selectSql.append(",u.").append(field).append(" AS ").append(field);
                }
            }
        }
        leftSql.append(" FROM (SELECT c.USER_INFO_ID,c.USER_CONFIG_INFO,uc.FIELD FROM piesat_user_configinfo c " +
                "LEFT JOIN piesat_user_userinfo_config uc ON c.USER_CONFIG_ID = uc.ID) a GROUP BY a.USER_INFO_ID) b");
        //拼接where条件语句
        StringBuilder whereSql = new StringBuilder(" WHERE 1 = 1");
        List<PiesatUserInfoConfigDTO> searchConfigList = piesatUserInfoConfigDAO.findAllByIsNotSearchOrderByCreateTime(0);
        List<Object> sqlParamList = new ArrayList<>();
        for (PiesatUserInfoConfigDTO configDTO : searchConfigList) {
            String formType = configDTO.getFormType();
            String field = configDTO.getField();
            boolean flag = false;
            if ("checkbox".equals(formType)) {
                JSONArray valueList = params.getJSONArray(field);
                if (!valueList.isEmpty()) {
                    flag = true;
                }
            } else {
                String valueStr = params.getString(field);
                if (StringUtils.isNotBlank(valueStr)) {
                    flag = true;
                }
            }
            if (flag) {
                if (!"username".equals(field) && !"password".equals(field) && !"telephone".equals(field) && !"email".equals(field)) {
                    whereSql.append(" AND b.").append(field);
                } else {
                    whereSql.append(" AND u.").append(field);
                }
                if (formType.contains("input")) {
                    whereSql.append(" LIKE ?");
                    sqlParamList.add("%" + params.getString(field) + "%");
                } else if ("checkbox".equals(formType)) {
                    whereSql.append(" REGEXP ?");
                    JSONArray valueList = params.getJSONArray(field);
                    StringBuilder regexp = new StringBuilder();
                    for (Object o : valueList) {
                        regexp.append("|").append((String)o);
                    }
                    sqlParamList.add(regexp.substring(1));
                } else {
                    whereSql.append(" = ?");
                    sqlParamList.add(params.getString(field));
                }
            }
        }
        //查找到当前部门下的所有部门ID作为参数条件
        List<PiesatDeptInfoDTO> deptList = piesatDeptInfoDAO.findAll();
        String deptId = params.getString("deptId");
        if (StringUtils.isNotBlank(deptId)) {
            JSONArray jsonArray = TreeUtil.listToTree(JSON.parseArray(JSON.toJSONString(deptList)), "id", "prentId", "children");
            JSONObject jsonObject = recursionTree(jsonArray, deptId);
            if (jsonObject != null) {
                List<String> idList = new ArrayList<>();
                idList.add(jsonObject.getString("id"));
                if (jsonObject.containsKey("children")) {
                    recursionAddId(jsonObject.getJSONArray("children"),idList);
                }
                whereSql.append(" AND u.DEPT_ID IN (");
                for (int i = 0; i < idList.size(); i++) {
                    if (i == 0) {
                        whereSql.append("?");
                    } else {
                        whereSql.append(",").append("?");
                    }
                    sqlParamList.add(idList.get(i));
                }
                whereSql.append(")");
            }
        }
        //角色条件
        JSONArray roleIdList = params.getJSONArray("roleIdList");
        if (!roleIdList.isEmpty()) {
            StringBuilder roleParamList = new StringBuilder();
            for (Object o : roleIdList) {
                roleParamList.append("|").append(o.toString());
            }
            whereSql.append(" AND r.roleList REGEXP ?");
            sqlParamList.add(roleParamList.substring(1));
        }
        //整合SQL
        StringBuilder allSql = new StringBuilder("SELECT u.ID AS id");
        StringBuilder countSql = new StringBuilder("SELECT COUNT(*) FROM piesat_user_userinfo u");
        allSql.append(selectSql)
                .append(",u.DEPT_ID AS deptId,u.LOCK_STATE AS lockState,u.LAST_LOGIN_TIME AS lastLoginTime,r.roleList as roleNameList" +
                " FROM piesat_user_userinfo u LEFT JOIN ")
                .append(leftSql)
                .append(" ON u.id = b.userId")
                .append(" LEFT JOIN (SELECT USER_ID,GROUP_CONCAT(ROLE_ID) as roleList FROM piesat_role_user_relation group by USER_ID) r " +
                        "ON u.ID = r.USER_ID")
                .append(whereSql.toString())
                .append(" ORDER BY u.CREATE_TIME DESC");
        countSql.append(" LEFT JOIN ")
                .append(leftSql)
                .append(" ON u.id = b.userId")
                .append(" LEFT JOIN (SELECT USER_ID,GROUP_CONCAT(ROLE_ID) as roleList FROM piesat_role_user_relation group by USER_ID) r " +
                        "ON u.ID = r.USER_ID")
                .append(whereSql.toString());
        Query basicQuery = entityManager.createNativeQuery(allSql.toString());
        Query countQuery = entityManager.createNativeQuery(countSql.toString());
        for (int i = 0; i < sqlParamList.size(); i++) {
            basicQuery.setParameter(i + 1, sqlParamList.get(i));
            countQuery.setParameter(i + 1,sqlParamList.get(i));
        }
        //总条数
        Object singleResult = countQuery.getSingleResult();
        BigInteger elementCount = (BigInteger)singleResult;
        basicQuery.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
        basicQuery.setMaxResults(pageable.getPageSize());
        basicQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String,Object>> dataList = basicQuery.getResultList();
        List<PiesatUserInfoConfigDTO> checkboxConfigList = registerConfigList.stream()
                .filter(configDTO -> "checkbox".equals(configDTO.getFormType()))
                .collect(Collectors.toList());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, String> deptHash = deptList.stream()
                .collect(Collectors.toMap(PiesatDeptInfoDTO::getId, PiesatDeptInfoDTO::getName));
        List<PiesatRoleInfoDTO> roleList = piesatRoleInfoDAO.findAll();
        Map<String, String> roleHash = roleList.stream()
                .collect(Collectors.toMap(PiesatRoleInfoDTO::getId, PiesatRoleInfoDTO::getName));
        List<Map<String, Object>> resultList = dataList.stream().map(map -> {
            for (PiesatUserInfoConfigDTO configDTO : checkboxConfigList) {
                Object value = map.get(configDTO.getField());
                if (value != null) {
                    map.put(configDTO.getField(),JSON.parseArray(value.toString()));
                }
            }
            Object lastLoginTime = map.get("lastLoginTime");
            if (lastLoginTime != null) {
                map.put("lsatLoginTime",sdf.format((Date)lastLoginTime));
            }
            Object dept = map.get("deptId");
            if (dept != null) {
                map.put("deptName",deptHash.get(dept.toString()));
            } else {
                map.put("deptName",null);
            }
            map.remove("deptId");
            Object roleNameList = map.get("roleNameList");
            if (roleNameList != null) {
                String[] splitRoleName = roleNameList.toString().split(",");
                List<String> nameList = new ArrayList<>();
                for (String splitName : splitRoleName) {
                    nameList.add(roleHash.get(splitName));
                }
                map.put("roleNameList",nameList);
            }
            return map;
        }).collect(Collectors.toList());
        Page<Map<String,Object>> page = new PageImpl<>(resultList,pageable,elementCount.intValue());
        return PageUtil.getPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOne(String id) {
        piesatUserInfoDAO.deleteById(id);
        piesatUserConfigInfoDAO.deleteAllByUserInfoId(id);
        piesatUserRoleRelationDAO.deleteAllByUserId(id);
    }

    @Override
    public void lock(JSONObject params) {
        String isLock = params.getString("isLock");
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(params.getString("id"));
        if (optional.isPresent()) {
            PiesatUserInfoDTO userInfoDTO = optional.get();
            if ("true".equals(isLock)) {
                userInfoDTO.setLockState(1);
            } else {
                userInfoDTO.setLockState(0);
            }
            piesatUserInfoDAO.save(userInfoDTO);
        }
    }

    @Override
    public String resetPassword(String userId) {
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(userId);
        if (optional.isPresent()) {
            PiesatUserInfoDTO userInfoDTO = optional.get();
            String newPassword = DESEncryptUtil.getRandomString(8);
            userInfoDTO.setPassword(passwordEncoder.encode(newPassword));
            piesatUserInfoDAO.save(userInfoDTO);
            return newPassword;
        }
        return null;
    }

    @Override
    public Map<String, Object> findByUserId(String userId) {
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(userId);
        return optional.map(dto -> {
            Map<String,Object> resultMap = new HashMap<>();
            resultMap.put("id",dto.getId());
            resultMap.put("deptId",dto.getDeptId());
            resultMap.put("username",dto.getUsername());
            resultMap.put("telephone",dto.getMobile());
            resultMap.put("email",dto.getEmail());
            List<ConfigInfoProjection> dataList = piesatUserInfoConfigDAO.findLeftConfigInfo(0, userId);
            dataList.forEach(projection -> {
                String configInfo = projection.getConfigInfo();
                if (configInfo != null) {
                    if ("checkbox".equals(projection.getFormType())) {
                        resultMap.put(projection.getField(),JSON.parseArray(configInfo));
                    } else {
                        resultMap.put(projection.getField(),configInfo);
                    }
                }
            });
            List<PiesatUserRoleRelationDTO> roleList = piesatUserRoleRelationDAO.findAllByUserId(userId);
            List<String> roleIdList = roleList.stream().map(PiesatUserRoleRelationDTO::getRoleId).collect(Collectors.toList());
            resultMap.put("roleIdList",roleIdList);
            return resultMap;
        }).orElse(null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> updateUser(JSONObject params) {
        Map<String,String> resultMap = new HashMap<>();
        List<PiesatUserInfoConfigDTO> formList = piesatUserInfoConfigDAO.findAllByIsNotRegisterOrderByCreateTime(0);
        if (StringUtils.isBlank(params.getString("deptId"))) {
            resultMap.put("success","false");
            resultMap.put("message","部门ID不能为空");
            return resultMap;
        }
        List<PiesatUserConfigInfoDTO> configInfoList = new ArrayList<>();
        //校验参数是否满足必填和规则
        for (PiesatUserInfoConfigDTO configDTO : formList) {
            String field = configDTO.getField();
            if ("password".equals(field)) {
                continue;
            }
            if (configDTO.getIsNotFill() == 0 && StringUtils.isBlank(params.getString(field))) {
                resultMap.put("success","false");
                resultMap.put("message",configDTO.getField() + "参数不能为空");
                return resultMap;
            }
            if (StringUtils.isNotBlank(configDTO.getVerifyRule())) {
                Pattern pattern = Pattern.compile(configDTO.getVerifyRule());
                Matcher matcher = pattern.matcher(params.getString(configDTO.getField()));
                if(!matcher.matches()) {
                    resultMap.put("success","false");
                    resultMap.put("message",configDTO.getField() + "不符合校验规则");
                    return resultMap;
                }
            }
            if ("username".equals(field) || "password".equals(field) || "telephone".equals(field) || "email".equals(field)) {
                continue;
            } else {
                PiesatUserConfigInfoDTO configInfoDTO = new PiesatUserConfigInfoDTO();
                configInfoDTO.setUserConfigId(configDTO.getId());
                if ("checkbox".equals(configDTO.getFormType())) {
                    configInfoDTO.setUserConfigInfo(params.getJSONArray(configDTO.getField()).toJSONString());
                } else {
                    configInfoDTO.setUserConfigInfo(params.getString(configDTO.getField()));
                }
                configInfoList.add(configInfoDTO);
            }
        }
        //校验登录方式的凭证是否唯一（用户名、手机号码、邮箱）
        List<PiesatUserInfoConfigDTO> loginConfigList = formList.stream()
                .filter(dto -> dto.getIsNotLogin() == 0)
                .collect(Collectors.toList());
        for (PiesatUserInfoConfigDTO dto : loginConfigList) {
            String field = dto.getField();
            PiesatUserInfoDTO existDTO = null;
            if ("username".equals(field)) {
                existDTO = piesatUserInfoDAO.findByUsername(params.getString(field));
            } else if ("telephone".equals(field)) {
                existDTO = piesatUserInfoDAO.findByMobile(params.getString(field));
            } else if ("email".equals(field)) {
                existDTO = piesatUserInfoDAO.findByEmail(params.getString(field));
            }
            if (existDTO != null && !existDTO.getId().equals(params.getString("id"))) {
                resultMap.put("success","false");
                resultMap.put("message",dto.getFieldName() + "已存在");
                return resultMap;
            }
        }
        //保存基本用户信息
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(params.getString("id"));
        if (optional.isPresent()) {
            PiesatUserInfoDTO userInfoDTO = optional.get();
            userInfoDTO.setUsername(params.getString("username"));
            userInfoDTO.setEmail(params.getString("email"));
            userInfoDTO.setMobile(params.getString("telephone"));
            userInfoDTO.setDeptId(params.getString("deptId"));
            userInfoDTO.setLockState(params.getInteger("lockState"));
            piesatUserInfoDAO.save(userInfoDTO);
            //保存额外用户信息
            configInfoList.forEach(dto -> dto.setUserInfoId(userInfoDTO.getId()));
            piesatUserConfigInfoDAO.deleteAllByUserInfoId(userInfoDTO.getId());
            piesatUserConfigInfoDAO.saveAll(configInfoList);
            //保存用户和角色关系
            JSONArray roleIdList = params.getJSONArray("roleIdList");
            piesatUserRoleRelationDAO.deleteAllByUserId(userInfoDTO.getId());
            if (!roleIdList.isEmpty()) {
                List<PiesatUserRoleRelationDTO> userRoleList = new ArrayList<>();
                for (Object o : roleIdList) {
                    PiesatUserRoleRelationDTO userRole = new PiesatUserRoleRelationDTO();
                    userRole.setRoleId(o.toString());
                    userRole.setUserId(userInfoDTO.getId());
                    userRoleList.add(userRole);
                }
                piesatUserRoleRelationDAO.saveAll(userRoleList);
            }
        }
        resultMap.put("success","true");
        resultMap.put("message","修改成功");
        return resultMap;
    }

    @Override
    public JSONArray getPermissionMenu(String userId) {
        List<String> roleIdList = piesatUserRoleRelationDAO.findAllByUserId(userId)
                .stream().map(PiesatUserRoleRelationDTO::getRoleId)
                .collect(Collectors.toList());
        if (!roleIdList.isEmpty()) {
            List<PiesatMenuInfoDTO> menuList = piesatMenuInfoDAO.findLeftRoleRelation(roleIdList)
                    .stream().distinct().collect(Collectors.toList());
            return TreeUtil.listToTree(JSON.parseArray(JSON.toJSONString(menuList)),"id","pid","children");
        }
        return new JSONArray();
    }

    @Override
    public Map<String, Object> findLoginUserInfo(String userId) {
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(userId);
        Map<String,Object> resultMap = new HashMap<>();
        if (optional.isPresent()) {
            PiesatUserInfoDTO userInfoDTO = optional.get();
            resultMap.put("username",userInfoDTO.getUsername());
            resultMap.put("telephone",userInfoDTO.getMobile());
            resultMap.put("email",userInfoDTO.getEmail());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            resultMap.put("createTime",sdf.format(userInfoDTO.getCreateTime()));
            List<String> roleIdList = piesatUserRoleRelationDAO.findAllByUserId(userId)
                    .stream().map(PiesatUserRoleRelationDTO::getRoleId).collect(Collectors.toList());
            List<String> roleNameList = new ArrayList<>();
            if (!roleIdList.isEmpty()) {
                 roleNameList = piesatRoleInfoDAO.findAllById(roleIdList).stream().map(PiesatRoleInfoDTO::getName).collect(Collectors.toList());
            }
            resultMap.put("roleNameList",roleNameList);
        }
        return resultMap;
    }

    @Override
    public List<String> getMenuButtonList(String userId, String menuId) {
        List<PiesatUserRoleRelationDTO> roleList = piesatUserRoleRelationDAO.findAllByUserId(userId);
        List<String> roleIdList = roleList.stream()
                .map(PiesatUserRoleRelationDTO::getRoleId)
                .collect(Collectors.toList());
        if (roleIdList.isEmpty()) {
            return new ArrayList<>();
        }
        return piesatResourceInfoDAO.findResourceLeftRoleRelation(menuId,"button",roleIdList)
                .stream()
                .distinct()
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, String> updatePassword(UpdatePasswordParam passwordParam, String userId) {
        Map<String,String> resultMap = new HashMap<>();
        Optional<PiesatUserInfoDTO> optional = piesatUserInfoDAO.findById(userId);
        if (optional.isPresent()) {
            PiesatUserInfoDTO userInfoDTO = optional.get();
            String checkPassword = passwordParam.getCheckPassword();
            String newPassword = passwordParam.getNewPassword();
            String oldPassword = passwordParam.getOldPassword();
            boolean matches = passwordEncoder.matches(oldPassword, userInfoDTO.getPassword());
            if (matches) {
                if (!checkPassword.equals(newPassword)) {
                    resultMap.put("success","false");
                    resultMap.put("message","两次输入新的密码不正确");
                    return resultMap;
                } else {
                    userInfoDTO.setPassword(passwordEncoder.encode(newPassword));
                    piesatUserInfoDAO.save(userInfoDTO);
                    resultMap.put("success","true");
                    resultMap.put("message","修改成功");
                    return resultMap;
                }
            } else {
                resultMap.put("success","false");
                resultMap.put("message","旧密码错误");
                return resultMap;
            }
        }
        resultMap.put("success","false");
        resultMap.put("message","用户不存在");
        return resultMap;
    }

    @Override
    public List<PiesatUserInfoDTO> findUserList() {
        return piesatUserInfoDAO.findAllByLockState(0);
    }

    @Override
    public Map<String, Object> getCharts() {
        Jedis jedis = JedisUtils.getJedis();
        Map<String,Object> returnMap = null;
        try{
            if(jedis.exists(FieldStaticConfig.ONLINE_USER_MESSAGE)){
                String map = jedis.get(FieldStaticConfig.ONLINE_USER_MESSAGE);
                returnMap = JSON.parseObject(map,new TypeReference<Map<String,Object>>(){});
            } else {
                returnMap = new HashMap<>();
                //在线人数
                Set<String> keys = jedis.keys(FieldStaticConfig.USER_MESSAGE_REDIS_PREFIX + "*");
                returnMap.put("onlineCount",keys.size());
                //总用户数
                Long allCount = piesatUserInfoDAO.count();
                returnMap.put("allCount",allCount);
                //最新登录用户
                List<Object[]> recentLogins = piesatUserInfoDAO.findRecentUser();
                List<Map<String,Object>> reRecentLogins = new ArrayList<>();
                recentLogins.forEach(obj -> {
                    Map<String,Object> map = new HashMap<>();
                    map.put("username",obj[0]);
                    map.put("lastLoginTime",obj[1]);
                    reRecentLogins.add(map);
                });
                returnMap.put("recentlyLogin", reRecentLogins);
                //活跃用户
                List<Object[]> loginTopNames = piesatUserLogDAO.getLoginTopName();
                List<Map<String,Object>> activeUser = new ArrayList<>();
                loginTopNames.forEach(obj -> {
                    if (obj != null && obj[1] != null) {
                        PiesatUserInfoDTO byUsername = piesatUserInfoDAO.findByUsername(obj[1].toString());
                        Map<String,Object> map = new HashMap<>();
                        map.put("username",byUsername.getUsername());
                        map.put("lastLoginTime",byUsername.getLastLoginTime());
                        activeUser.add(map);
                    }
                });
                returnMap.put("activeUser",activeUser);
                //今日登录人数
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Calendar calendar = Calendar.getInstance();
                String today = format.format(calendar.getTime()) + " 00:00:00";
                calendar.add(Calendar.DATE, 1);
                String tomorrow = format.format(calendar.getTime()) + " 23:59:59";
                Date todayD = format1.parse(today);
                Date tomorrowD = format1.parse(tomorrow);
                Long todayCount = piesatUserInfoDAO.countAllByLastLoginTimeBetween(todayD, tomorrowD);
                returnMap.put("todayCount",todayCount);
                jedis.set(FieldStaticConfig.ONLINE_USER_MESSAGE,JSONObject.toJSONString(returnMap),"NX","EX",5 * 60);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            JedisUtils.close(jedis);
        }
        return returnMap;
    }

    @Override
    public PiesatUserInfoDTO findByEmail(String email) {
        return piesatUserInfoDAO.findByEmail(email);
    }

    @Override
    public PiesatUserInfoDTO findByMobile(String mobile) {
        return piesatUserInfoDAO.findByMobile(mobile);
    }

    @Override
    public List<String> listAllUserName() {
        List<String> names = piesatUserInfoDAO.listAllUserNames();
        if(names == null){
            names = Collections.emptyList();
        }
        return names;
    }


    private JSONObject recursionTree(JSONArray jsonArray, String id) {
        JSONObject j = null;
        for (Object o : jsonArray) {
            JSONObject jsonObject = (JSONObject)o;
            if (jsonObject.getString("id").equals(id)) {
                return jsonObject;
            }
            if (jsonObject.containsKey("children")) {
                j = recursionTree(jsonObject.getJSONArray("children"),id);
            }
        }
        return j;
    }

    private void recursionAddId(JSONArray jsonArray,List<String> idList) {
        for (Object o : jsonArray) {
            JSONObject jsonObject = (JSONObject)o;
            if (jsonObject.containsKey("children")) {
                recursionAddId(jsonObject.getJSONArray("children"),idList);
            }
            idList.add(jsonObject.getString("id"));
        }
    }
}
